package com.cn.controller;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
 










import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.kafka.common.KafkaException;
import org.redisson.api.RLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
 
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.cn.annotation.MethodRedisLimit;
import com.cn.component.SnowFlake;
import com.cn.constant.ProConstant;
import com.cn.domain.OrderEntity;
import com.cn.kafka.KafkaSender;
import com.cn.service.DistributedLocker;
import com.cn.service.OrderService;
import com.cn.zooKeeper.ZkClient;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
 

@RestController  
public class OrderController {

	private Logger  logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
	private OrderService orderService;

    @Autowired
    private ZkClient zkclient;
	 @Autowired
	 DistributedLocker distributedLocker;
	 @Autowired
	    private KafkaSender kafkaSender;
 
    @Autowired
    private  DefaultRedisScript<Long> redisScript;
    @Autowired
    private DefaultRedisScript<Long> redisNumScript;
    
	@Autowired  
    private RedisTemplate redisTemplate;
	
	private int p=0; 
    
	@RequestMapping("/getorderList") 
	public List<OrderEntity> getOrderList(OrderEntity order){
		if(order ==null){
			order = new OrderEntity();
		}
		return this.orderService.findOrderEntityByWhere(order);
	}
	
	@RequestMapping("/secondKill")
	@HystrixCommand(
	          fallbackMethod = "getOrderPageListFallback",
	          threadPoolProperties = {  //10个核心线程池,超过20个的队列外的请求被拒绝; 当一切都是正常的时候，线程池一般仅会有1到2个线程激活来提供服务
	                  @HystrixProperty(name = "coreSize", value = "10"),
	                  @HystrixProperty(name = "maxQueueSize", value = "100"),
	                  @HystrixProperty(name = "queueSizeRejectionThreshold", value = "20")},
	          commandProperties = {
	                  @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "10000"), //命令执行超时时间
	                  @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "2"), //若干10s一个窗口内失败三次, 则达到触发熔断的最少请求量
	                  @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "30000") //断路30s后尝试执行, 默认为5s
	  })
	public void secondKill(){
		 
		OrderEntity orderEntity = new OrderEntity();
		orderEntity.setProductId(1);
		orderEntity.setModifyTime(new Date());
		
		orderEntity.setNum(1);
		orderEntity.setUserId(1);
		//SnowFlake snowFlake = new SnowFlake(0, 0);
		// String orderNo = snowFlake.nextId()+"";
		String orderNo = UUID.randomUUID().toString();
		orderEntity.setOrderNo(orderNo);
	  	//this.orderService.secondKill(orderEntity);
		RLock rlock = this.distributedLocker.lock("aaa");
		System.out.println(Thread.currentThread().getId()+" controller");
	    rlock.lock();
		this.orderService.secondKillRedis(orderEntity);
		rlock.unlock();
	 
	}
	 public String getOrderPageListFallback( ){
	      logger.error("===================== 执行降级策略");
	      return "error";
	  }
		@RequestMapping("/ShowTestList")
		@MethodRedisLimit(fallback="getOrderPageListFallback")
		public void ShowTestList(){
			System.out.println("roorsdf djpe dhoeshow");
			
		}
		@RequestMapping("/withoutShowTestList")
		 
		public void withoutShowTestList(){
			System.out.println("withoutShowTestList djpe dhoeshow");
			
		}
	 
	@RequestMapping("/pushList")
	public void pushList(){
	 
 
		OrderEntity orderEntity = new OrderEntity();
		orderEntity.setModifyTime(new Date());
		orderEntity.setProductId(1);
		orderEntity.setNum(1);
		orderEntity.setUserId(1);
		SnowFlake snowFlake = new SnowFlake(0,0);
		orderEntity.setOrderNo(snowFlake.nextId()+"");
		 
	  	//this.orderService.secondKill(orderEntity);
		redisTemplate.opsForList().rightPush(ProConstant.QUEUE+1, orderEntity);
		 
	 
		 
	}
	@RequestMapping("/luaKill")
	public void luaKill(){
    	int productId=1;
    	int orderNum=1;
    	int userId=1;
    	List<String> keys= new ArrayList<String>();
    	keys.add("ProductNum");
    	keys.add("JsonList"+productId);
		this.redisTemplate.execute(redisScript, keys, productId,orderNum,userId);
	}
	@RequestMapping("/kafkaKill")
	public void kafkaKill(){
    	int productId=1;
    	int orderNum=1;
    	int userId=1;
    	List<String> keys= new ArrayList<String>();
    	keys.add("ProductNum");
    
		Long num = (Long) this.redisTemplate.execute(redisNumScript, keys, productId,orderNum,userId);
		if(num >0){
			try {
				kafkaSender.sendTopicsMessage("order_list", productId+"_"+orderNum+"_"+userId);
			} catch (KafkaException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	@RequestMapping("/zkKill")
	public void zkKill() throws Exception{
		InterProcessMutex mutex = new InterProcessMutex( this.zkclient.getClient(), "/curator/lock");
		try {
			mutex.acquire();
			System.out.println("p is"+ p );
			System.out.println(Thread.currentThread().getId()+" id");
			p++;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			 
				mutex.release();
			 
		}
	}
}

